package com.sky.service.admin.impl;


import com.sky.dto.GoodsSalesDTO;


import com.sky.exception.BaseException;
import com.sky.mapper.admin.ReportMapper;
import com.sky.service.admin.ReportService;

import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;


import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;


import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
public class ReportServiceImpl implements ReportService {
    @Autowired
    private ReportMapper reportMapper;
    /**
     * 营业额统计
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO report(LocalDate begin, LocalDate end) {
        log.info("营业额统计");
        List<LocalDate> allDays=getAllDays(begin,end);
        //按天查询金额
        List<OrderDayAmountVO> orderDayAmountVOS=reportMapper.turnoverStatistics(begin,end.plusDays(1));
        List<BigDecimal> amountList = new ArrayList<>();
        //封装每天的订单金额数据
        for (LocalDate oneDay : allDays) {
            OrderDayAmountVO orderDayAmountVO = orderDayAmountVOS.stream().filter(o -> o.getOrderTime().equals(oneDay))
                    .findFirst().orElse(null);
            if (orderDayAmountVO==null){
                amountList.add(new BigDecimal(0.0));
            }else {
                amountList.add(orderDayAmountVO.getAmount());
            }
        }
        //封装数据
        TurnoverReportVO reportVO=TurnoverReportVO.builder()
                .dateList(org.springframework.util.StringUtils.collectionToCommaDelimitedString(allDays))
                .turnoverList(StringUtils.collectionToCommaDelimitedString(amountList))
                .build();
        return reportVO;
        /*end=end.plusDays(1);
        //参数判空
        if(begin==null || end==null){
            throw new BaseException("参数异常");
        }
        //指定时间段之内的每一天的销售额
//        *
//         *  2种做法：
//         *    第一种做法：简单， 循环，一天一天的查询
//         *    第二种做法：复杂，一条sql语句查询出来

        List<String> dataList = new ArrayList<>();
        List<Double> turnoverList = new ArrayList<>();
        while (begin.isBefore(end)){
            dataList.add(begin.toString());
            //都要查询当天的数据

            Double salesVolume =  reportMapper.selectSalesVolumesByDay(begin.toString());

            if(salesVolume==null){
                salesVolume=0.0; //当天查询到数据，重置为0
            }
            turnoverList.add(salesVolume);

            //begin往后数一天
            begin = begin.plusDays(1);
        }

        //封装给前端
        String dateListStr = StringUtils.join(dataList, ",");
        String turnoverListStr = StringUtils.join(turnoverList, ",");
        TurnoverReportVO turnoverReportVO = new TurnoverReportVO();
        turnoverReportVO.setTurnoverList(turnoverListStr);
        turnoverReportVO.setDateList(dateListStr);
        return turnoverReportVO;*/
    }

    /**
     * 订单统计
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO orderReport(LocalDate begin, LocalDate end) {
        log.info("订单统计");
        List<LocalDate> allDays = getAllDays(begin, end);
        //每日订单数 每日有效订单
        List<Integer> totalList = new ArrayList<>();
        List<Integer> completeList = new ArrayList<>();
        List<OrderDayAmountVO> orderDayAmountVOS = reportMapper.orderReport(begin, end.plusDays(1));
        for (LocalDate allDay : allDays) {
            OrderDayAmountVO orderDayAmountVO = orderDayAmountVOS.stream().filter(o -> o.getOrderTime().equals(allDay))
                    .findFirst().orElse(null);
            if (orderDayAmountVO == null) {
                totalList.add(0);
                completeList.add(0);
            } else {
                totalList.add(orderDayAmountVO.getTotalNum());
                completeList.add(orderDayAmountVO.getCompleteNum());
            }
        }
            //订单总数
            Integer totalNum = totalList.stream().reduce(Integer::sum).get();
            Integer complete = completeList.stream().reduce(Integer::sum).get();
            double rate = 0d;
            if (totalNum != 0) {
                rate = complete * 1d / totalNum;
            }
            //封装返回
            OrderReportVO orderReportVO = OrderReportVO.builder().dateList(org.springframework.util.StringUtils.collectionToCommaDelimitedString(allDays))
                    .validOrderCountList(org.springframework.util.StringUtils.collectionToCommaDelimitedString(completeList))
                    .orderCountList(org.springframework.util.StringUtils.collectionToCommaDelimitedString(totalList))
                    .totalOrderCount(totalNum)
                    .validOrderCount(complete)
                    .orderCompletionRate(rate)
                    .build();
        return orderReportVO;
    }

    /**
     * 销量统计
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
        log.info("销量统计");
        List<GoodsSalesDTO> salesDTOS=reportMapper.dishTop10(begin,end.plusDays(1));
        //获取菜品集合
        List<String> nameList = salesDTOS.stream().map(GoodsSalesDTO::getName).collect(Collectors.toList());
        //获取销量集合
        List<Integer> numList = salesDTOS.stream().map(GoodsSalesDTO::getNumber).collect(Collectors.toList());
        //封装返回
        SalesTop10ReportVO reportVO = SalesTop10ReportVO.builder()
                .nameList(org.springframework.util.StringUtils.collectionToCommaDelimitedString(nameList))
                .numberList(org.springframework.util.StringUtils.collectionToCommaDelimitedString(numList))
                .build();
        return reportVO;
    }

    /**
     * 用户统计
     * @param begin
     * @param end
     * @return
     */
    @Override
    public UserReportVO userReport(LocalDate begin, LocalDate end) {
        log.info("用户统计");
        String oldBegin = begin.toString();
        String oldEnd = end.toString();
        //获取日期集合
        ArrayList<String> dateList = new ArrayList<>();
        //获取用户总量
        ArrayList<Integer> totalUserList = new ArrayList<>();
        //新增用户集合
        ArrayList<Integer> newUserList = new ArrayList<>();
         end = end.plusDays(1);
         while (begin.isBefore(end)){
             dateList.add(begin.toString());
             begin = begin.plusDays(1);
         }
         //查询总用户数量
        Integer total=reportMapper.getAllUserByDate(oldBegin);

         //查询新增用户数量
        Map<String,Object> res=reportMapper.getNewUserCount(oldBegin,oldEnd,dateList);

        //封装数据
        for (String date : dateList) {
            //获取每一天新增
            Integer newUsers =Integer.parseInt(res.get(date).toString());
            newUserList.add(newUsers);
            //累计当日用户的总数
            total+=newUsers;
            totalUserList.add(total);
        }
        UserReportVO userReportVO=UserReportVO.builder()
                .dateList(org.springframework.util.StringUtils.collectionToCommaDelimitedString(dateList))
                .totalUserList(org.springframework.util.StringUtils.collectionToCommaDelimitedString(totalUserList))
                .newUserList(org.springframework.util.StringUtils.collectionToCommaDelimitedString(newUserList))
                .build();
        return userReportVO;

    }

    /**
     * 导出运营数据报表
     * @param response
     */
    @Override
    public void export(HttpServletResponse response) throws IOException {
        //读取数据表
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("statement/运营数据报表.xlsx");
        //创建表格对象
        XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
        //获取sheet页
        XSSFSheet sheet = workbook.getSheetAt(0);
        //设置时间
        XSSFRow row2 = sheet.getRow(1);
        LocalDate now = LocalDate.now();
        LocalDate begin = now.minusDays(30);
        log.info("时间: "+begin+"至"+now);
        row2.getCell(0).setCellValue("时间: "+begin+"至"+now);
        //设置概览数据
        //先从数据库读取
        OrderDayAmountVO orderDayAmountVO=reportMapper.exportData(begin,now);
        BusinessDataVO businessDataVO = buildBusiness(orderDayAmountVO, now);

        //营业额
        Double turnover = businessDataVO.getTurnover();
        //计算订单完成率
        Double rate = businessDataVO.getOrderCompletionRate();
        //新增用户
        Integer users = businessDataVO.getNewUsers();
        //平均客单价
        Double price = businessDataVO.getUnitPrice();
        //有效订单
        Integer validOrderCount = businessDataVO.getValidOrderCount();
        //封装概览数据
        XSSFRow row4 = sheet.getRow(3);
        row4.getCell(1).setCellValue(turnover);
        row4.getCell(3).setCellValue(rate);
        row4.getCell(5).setCellValue(users);
        XSSFRow row5 = sheet.getRow(4);
        row5.getCell(1).setCellValue(validOrderCount);
        row5.getCell(3).setCellValue(price);
        //设置明细数据
        List<OrderDayAmountVO> orderDayAmountVOS = reportMapper.orderReport(begin, now);
        //定义起始索引
        int beginIndex = 7;
        //循环设置数据
        while (!begin.equals(now)){
            //设置临时日期
            LocalDate temp=begin;
            //过滤日期
            OrderDayAmountVO amountVO = orderDayAmountVOS.stream().filter(o -> o.getOrderTime().equals(temp)).findFirst().orElse(null);
            BusinessDataVO dataVO = buildBusiness(amountVO, begin);
            XSSFRow dataRow = sheet.getRow(beginIndex);
            dataRow.getCell(0).setCellValue(begin.toString());
            dataRow.getCell(1).setCellValue(dataVO.getTurnover());
            dataRow.getCell(2).setCellValue(dataVO.getValidOrderCount());
            dataRow.getCell(3).setCellValue(dataVO.getOrderCompletionRate());
            dataRow.getCell(4).setCellValue(dataVO.getUnitPrice());
            dataRow.getCell(5).setCellValue(dataVO.getNewUsers());
            beginIndex++;
            begin=begin.plusDays(1);
        }
        //写出到文件
        workbook.write(response.getOutputStream());
        workbook.close();
    }
    /**
     * 此方法为封装每一天明细
     */
    private BusinessDataVO buildBusiness(OrderDayAmountVO orderDayAmountVO,LocalDate date ){
        //封装新增用户数
        Integer users = reportMapper.getNewUsers(date,date.plusDays(1));
        if (orderDayAmountVO==null){
            return new BusinessDataVO(
                    0.0,
                    0,
                    0.0,
                    0.0,
                    users
            );
        }
        Integer completeNum = orderDayAmountVO.getCompleteNum();
        Integer totalNum = orderDayAmountVO.getTotalNum();
        BigDecimal amount = orderDayAmountVO.getAmount();
        //平均客单价
        double price=0;
        if (completeNum!=0){
            price=orderDayAmountVO.getAmount().doubleValue()/completeNum;
        }
        //封装数据
        BusinessDataVO businessDataVO=new BusinessDataVO().builder()
                .turnover(amount.doubleValue())
                .orderCompletionRate(completeNum*1d/totalNum)
                .unitPrice(price)
                .validOrderCount(completeNum)
                .newUsers(users).build();
        return businessDataVO;
    }

    /**
     * 获取所有日期
     * @param begin
     * @param end
     * @return
     */
    private List<LocalDate> getAllDays(LocalDate begin, LocalDate end) {
        ArrayList<LocalDate> allDays = new ArrayList<>();
        allDays.add(begin);
        while (!begin.equals(end)){
            begin=begin.plusDays(1);
            allDays.add(begin);
        }
        return allDays;
    }
}
